package nl.cypherpunk.statelearner;

import de.learnlib.api.logging.LearnLogger;
import net.automatalib.words.Alphabet;
import nl.cypherpunk.statelearner.fuzzing.FuzzingBasedTesting;
import nl.cypherpunk.statelearner.fuzzing.TLSSUT;
import nl.cypherpunk.statelearner.tls.TLSConfig;
import nl.cypherpunk.statelearner.tls.TLSSUL;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.text.SimpleDateFormat;
import java.util.Date;

public class Fuzzing {
    LearningConfig config;
    Alphabet<String> alphabet;
    Alphabet<String> meaning;
    TLSSUT sut;

    public Fuzzing(LearningConfig config) throws Exception {
        this.config = config;
        File outputDir = new File(config.output_dir);
        outputDir.mkdirs();
        LearnLogger log = LearnLogger.getLogger(Learner.class.getSimpleName());

        // Check the type of learning we want to do and create corresponding configuration and SUL
        if(config.type == LearningConfig.TYPE_TLS) {
            log.logConfig("Using TLS SUL");

            // Create the TLS SUT
            sut = new TLSSUT(new TLSConfig(config));
            alphabet = ((TLSSUT)sut).getAlphabet();
            meaning = sut.getMeaning();
        }
    }

    public Fuzzing(Learner learner) throws Exception {
        this.config = learner.config;
        //File outputDir = new File(config.output_dir);
        //outputDir.mkdirs();
        LearnLogger log = LearnLogger.getLogger(Learner.class.getSimpleName());

        // Check the type of learning we want to do and create corresponding configuration and SUL
        if(config.type == LearningConfig.TYPE_TLS) {
            log.logConfig("Using TLS SUL");

            // Create the TLS SUT
            sut = new TLSSUT(new TLSConfig(config));
            alphabet = ((TLSSUT)sut).getAlphabet();
            meaning = sut.getMeaning();
        }
    }

    public void fuzz() throws Exception, IOException, InterruptedException {

        System.out.println("Using TLS SUL");

        FuzzingBasedTesting fuzzingBasedTesting =
                new FuzzingBasedTesting(this.config.output_dir,"output_server/openssl3.0.0-dev.dot", sut, alphabet, this.config.coverage_cmd);

        // define the fuzzing number on every state
        fuzzingBasedTesting.randomWalkWithFuzzing(200, 60*20);
    }

    public void fuzzAfterLearn() throws Exception, IOException, InterruptedException {
        System.out.println("Using TLS SUL");
        FuzzingBasedTesting fuzzingBasedTesting =
                new FuzzingBasedTesting(this.config.output_dir,this.config.output_dir+File.separator+"learnedModel.dot", sut, alphabet,this.config.coverage_cmd);
        // define the fuzzing number on every state
        fuzzingBasedTesting.randomWalkWithFuzzing(200, 60*20);
    }


    public static void main(String[] args) throws Exception {
        if(args.length < 1) {
            System.err.println("Invalid number of parameters");
            System.exit(-1);
        }
        Date startDate = new Date();

        LearningConfig config = new LearningConfig(args[0]);


        Learner learner = new Learner(config);
        learner.learn();
        Fuzzing fuzz = new Fuzzing(learner);
        fuzz.fuzzAfterLearn();
        /*
        Fuzzing fuzz = new Fuzzing(config);
        fuzz.fuzz();
        */
        Date endDate = new Date();
        int minutes = (int) ((endDate.getTime() - startDate.getTime())/(1000 * 60));
        System.out.println("The total time is "+ minutes +" minutes");
    }
}
